From 66edd49a38a5f5eb57e12b1302adae2e7bc05594 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 15:24:00 +0100 Subject: [PATCH] Add code to make handling domain poweroff/reboot symmetrical between paravirtualized and fully virtualized. This approach uses the new sched_op to handle other domains than the current domain. The new code, SCHEDOP_remote_shutdown, is very much like SCHEDOP_shutdown, but is called with the id of the domain which is to be shut down. This allows fully virtualized shutdown and para-virtualized shutdown to be identical from that point forward. A paravirtualized domain uses sched_op to shut down and set the reason code. This will send a VIRQ_DOM_EXC, which can be handled in dom0 by control software. In some ways, this resembles SIGCHILD/waitpid, and is a reasonable model. The fully virtualized case has qemu invoke xm directly. This is a different path than paravirtualized. It also removes decision and policy making choices from the rest of the control software and places it within qemu. When any dom0 logic eventually gets a VIRQ_DOM_EXC, the information about the domain is gone having been destroyed by xm. A libxenctrl wrapper, xc_shutdown_domain has been added and qemu now calls it. As a freebie, #if 0 some very verbose logging code in qemu. Totally unrelated, but as long as I was there... Signed-off-by: Ben Thomas --- .../drivers/xen/privcmd/privcmd.c | 1 + tools/ioemu/target-i386-dm/helper2.c | 45 +++++++++++++------ tools/ioemu/vl.c | 2 + tools/libxc/xc_domain.c | 29 ++++++++++++ tools/libxc/xenctrl.h | 15 +++++++ xen/common/schedule.c | 24 ++++++++++ xen/include/public/sched.h | 13 ++++++ 7 files changed, 116 insertions(+), 13 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index 52364f9aeb..e572fa7c79 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -277,6 +277,7 @@ static int __init privcmd_init(void) set_bit(__HYPERVISOR_mmu_update, hypercall_permission_map); set_bit(__HYPERVISOR_mmuext_op, hypercall_permission_map); set_bit(__HYPERVISOR_xen_version, hypercall_permission_map); + set_bit(__HYPERVISOR_sched_op, hypercall_permission_map); privcmd_intf = create_xen_proc_entry("privcmd", 0400); if (privcmd_intf != NULL) diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index af4a8e8d8b..a596c6edab 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -409,12 +409,20 @@ int xc_handle; void destroy_hvm_domain(void) { - extern FILE* logfile; - char destroy_cmd[32]; - - sprintf(destroy_cmd, "xm destroy %d", domid); - if (system(destroy_cmd) == -1) - fprintf(logfile, "%s failed.!\n", destroy_cmd); + int xcHandle; + int sts; + + xcHandle = xc_interface_open(); + if (xcHandle < 0) + fprintf(logfile, "Cannot acquire xenctrl handle\n"); + else { + sts = xc_domain_shutdown(xcHandle, domid, SHUTDOWN_poweroff); + if (sts != 0) + fprintf(logfile, "? xc_domain_shutdown failed to issue poweroff, sts %d, errno %d\n", sts, errno); + else + fprintf(logfile, "Issued domain %d poweroff\n", domid); + xc_interface_close(xcHandle); + } } fd_set wakeup_rfds; @@ -480,13 +488,24 @@ int main_loop(void) static void qemu_hvm_reset(void *unused) { - char cmd[64]; - - /* pause domain first, to avoid repeated reboot request*/ - xc_domain_pause(xc_handle, domid); - - sprintf(cmd, "xm shutdown -R %d", domid); - system(cmd); + int xcHandle; + int sts; + + /* pause domain first, to avoid repeated reboot request*/ + xc_domain_pause(xc_handle, domid); + + xcHandle = xc_interface_open(); + if (xcHandle < 0) + fprintf(logfile, "Cannot acquire xenctrl handle\n"); + else { + sts = xc_domain_shutdown(xcHandle, domid, SHUTDOWN_reboot); + if (sts != 0) + fprintf(logfile, "? xc_domain_shutdown failed to issue reboot, sts %d\n", sts); + else + fprintf(logfile, "Issued domain %d reboot\n", domid); + xc_interface_close(xcHandle); + } + } CPUState * cpu_init() diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 6586f77deb..da009dd11b 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -2556,8 +2556,10 @@ static int set_mm_mapping(int xc_handle, return -1; } +#if 0 /* Generates lots of log file output - turn on for debugging */ for (i = 0; i < nr_pages; i++) fprintf(stderr, "set_map result i %x result %lx\n", i, extent_start[i]); +#endif return 0; } diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index ea2ca76d1b..3b9abd11f8 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -58,6 +58,35 @@ int xc_domain_destroy(int xc_handle, return do_dom0_op(xc_handle, &op); } +int xc_domain_shutdown(int xc_handle, + uint32_t domid, + int reason) +{ + int ret = -1; + sched_remote_shutdown_t arg; + DECLARE_HYPERCALL; + + hypercall.op = __HYPERVISOR_sched_op; + hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown; + hypercall.arg[1] = (unsigned long)&arg; + arg.domain_id = domid; + arg.reason = reason; + + if ( mlock(&arg, sizeof(arg)) != 0 ) + { + PERROR("Could not lock memory for Xen hypercall"); + goto out1; + } + + ret = do_xen_hypercall(xc_handle, &hypercall); + + safe_munlock(&arg, sizeof(arg)); + + out1: + return ret; +} + + int xc_vcpu_setaffinity(int xc_handle, uint32_t domid, int vcpu, diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index fce21b7334..3bc124d77d 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -206,6 +206,21 @@ int xc_domain_unpause(int xc_handle, int xc_domain_destroy(int xc_handle, uint32_t domid); +/** + * This function will shutdown a domain. This is intended for use in + * fully-virtualized domains where this operation is analogous to the + * sched_op operations in a paravirtualized domain. The caller is + * expected to give the reason for the shutdown. + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm domid the domain id to destroy + * @parm reason is the reason (SHUTDOWN_xxx) for the shutdown + * @return 0 on success, -1 on failure + */ +int xc_domain_shutdown(int xc_handle, + uint32_t domid, + int reason); + int xc_vcpu_setaffinity(int xc_handle, uint32_t domid, int vcpu, diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 0b1644ea5a..5fe6cb4304 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -413,6 +413,30 @@ long do_sched_op(int cmd, GUEST_HANDLE(void) arg) break; } + case SCHEDOP_remote_shutdown: + { + struct domain *d; + struct sched_remote_shutdown sched_remote_shutdown; + + if ( !IS_PRIV(current->domain) ) + return -EPERM; + + ret = -EFAULT; + if ( copy_from_guest(&sched_remote_shutdown, arg, 1) ) + break; + + ret = -ESRCH; + d = find_domain_by_id(sched_remote_shutdown.domain_id); + if ( d == NULL ) + break; + + domain_shutdown(d, (u8)sched_remote_shutdown.reason); + put_domain(d); + ret = 0; + + break; + } + default: ret = -ENOSYS; } diff --git a/xen/include/public/sched.h b/xen/include/public/sched.h index 28e86c0d76..27f321e080 100644 --- a/xen/include/public/sched.h +++ b/xen/include/public/sched.h @@ -64,6 +64,19 @@ typedef struct sched_poll { } sched_poll_t; DEFINE_GUEST_HANDLE(sched_poll_t); +/* + * Declare a shutdown for another domain. The main use of this function is + * in interpreting shutdown requests and reasons for fully-virtualized + * domains. A para-virtualized domain may use SCHEDOP_shutdown directly. + * @arg == pointer to sched_remote_shutdown structure. + */ +#define SCHEDOP_remote_shutdown 4 +typedef struct sched_remote_shutdown { + domid_t domain_id; /* Remote domain ID */ + unsigned int reason; /* SHUTDOWN_xxx reason */ +} sched_remote_shutdown_t; +DEFINE_GUEST_HANDLE(sched_remote_shutdown_t); + /* * Reason codes for SCHEDOP_shutdown. These may be interpreted by control * software to determine the appropriate action. For the most part, Xen does -- 2.30.2